package cn.cqie.frame.service.impl;

import cn.cqie.frame.bo.add.AddUserReqBo;
import cn.cqie.frame.bo.query.QueryUserListReqBo;
import cn.cqie.frame.bo.update.UpdateUserChangePsBo;
import cn.cqie.frame.bo.update.UpdateUserPsBo;
import cn.cqie.frame.bo.update.UpdateUserReqBo;
import cn.cqie.frame.bo.update.UpdateUserStatusReqBo;
import cn.cqie.frame.dto.UserContext;
import cn.cqie.frame.entity.SysRole;
import cn.cqie.frame.entity.SysUser;
import cn.cqie.frame.bo.*;
import cn.cqie.frame.entity.UserRole;
import cn.cqie.frame.enums.YesOrNo;
import cn.cqie.frame.mapper.SysUserMapper;
import cn.cqie.frame.service.SysRoleService;
import cn.cqie.frame.service.SysUserService;
import cn.cqie.frame.service.UserRoleService;
import cn.cqie.frame.utils.*;
import cn.cqie.frame.vo.UserVo;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author XYHL
 * @since 2021-09-03
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    UserRoleService userRoleService;
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysRoleService sysRoleService;

    /**
     * 获取当前登录用户的信息
     * @param id
     * @return
     */
    @Override
    public UserVo getInfoById(Long id) {
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUser::getId, id);
        SysUser sysUser = baseMapper.selectById(id);
        AssertUtil.isNotNull(sysUser, "用户不存在");
        UserVo user = BeanUtil.toBean(sysUser, UserVo.class);
        return user;
    }

    /**
     * 登录
     * @param bo
     * @return
     */
    @Override
    public String login(LoginBo bo) {
        AssertUtil.isNotBlank(bo.getAccount(), "登录账号不能为空");
        AssertUtil.isNotBlank(bo.getPassword(), "登录密码不能为空");
        LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysUser::getAccount, bo.getAccount());
        SysUser sysUser = baseMapper.selectOne(lqw);
        AssertUtil.isNotNull(sysUser, "用户不存在");
        String md5Password = MD5Utils.stringToMD5(bo.getPassword());
        AssertUtil.isTrue(md5Password.equals(sysUser.getPassword()), "密码不正确");
        String token = TokenUtil.sign(sysUser);
        baseMapper.update(null, new LambdaUpdateWrapper<SysUser>()
                .set(SysUser::getToken, token)
                .eq(SysUser::getId, sysUser.getId()));
        return token;
    }

    /**
     * 退出登录
     */
    @Override
    public void logOut() {
        Long userId = UserContext.get().getId();
        UserContext.remove();
        baseMapper.update(null, new LambdaUpdateWrapper<SysUser>()
                .set(SysUser::getToken, null)
                .eq(SysUser::getId, userId));
    }

    /**
     * 插入用户信息
     * @param bo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public synchronized UserVo addUser(AddUserReqBo bo) {
        AssertUtil.isNotBlank(bo.getUsername(), "姓名不能为空");
        AssertUtil.isNotBlank(bo.getAccount(), "工号不能为空");
        LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysUser::getAccount, bo.getAccount());
        lqw.eq(SysUser::getStatus, YesOrNo.YES.getCode());
        SysUser sysUser = baseMapper.selectOne(lqw);
        AssertUtil.isNull(sysUser, "账号已经存在");
        LocalDateTime sysTime = DateUtils.getLocalDateTime();
        SysUser insertSysUser = new SysUser();
        insertSysUser.setStatus(YesOrNo.YES.getCode());
        insertSysUser.setUsername(bo.getUsername());
        insertSysUser.setAccount(bo.getAccount());
        insertSysUser.setDelFlag(YesOrNo.NO.getCode());
        insertSysUser.setPassword(MD5Utils.stringToMD5("123456"));
        insertSysUser.setCreateTime(sysTime);
        insertSysUser.setUpdateTime(sysTime);
        int insert = baseMapper.insert(insertSysUser);
        AssertUtil.isTrue(insert > 0, "插入用户失败");
        bo.setUserId(insertSysUser.getId());
        bo.setRoleIdList(bo.getRoleIdList());
        userRoleService.addUserRole(bo);
        return BeanUtil.toBean(insertSysUser, UserVo.class);
    }

    /**
     * 更新用户信息和对应的权限信息
     * @param bo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public Boolean updateUser(UpdateUserReqBo bo) {
        AssertUtil.isNotBlank(bo.getUsername(), "姓名不能为空");
        LambdaUpdateWrapper<SysUser> lqw = new LambdaUpdateWrapper<>();
        lqw.set(SysUser::getUsername,bo.getUsername())
                .set(SysUser::getUpdateTime, DateUtils.getLocalDateTime())
                .eq(SysUser::getId, bo.getId());
        int update = baseMapper.update(null, lqw);
        bo.setUserId(bo.getId());
        LambdaQueryWrapper<UserRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserRole::getUserId,bo.getUserId());
        boolean remove = userRoleService.remove(lambdaQueryWrapper);
        boolean b1 = false;
        if (remove){
            AddUserReqBo addUserReqBo = new AddUserReqBo();
            addUserReqBo.setUserId(bo.getUserId());
            addUserReqBo.setRoleIdList(bo.getRoleIdList());
             b1 = userRoleService.addUserRole(addUserReqBo);
        }
        AssertUtil.isTrue(update > 0 && b1, "更新失败");
        return update > 0 && b1 ;
    }

    /**
     * 用户的启停
     * @param bo
     * @return
     */
    @Override
    public Boolean changeUserStatus(UpdateUserStatusReqBo bo) {
        AssertUtil.isNotNull(bo.getId(), "用户ID不能为空");
        AssertUtil.isNotBlank(bo.getStatus(), "状态不能为空");
        LambdaUpdateWrapper<SysUser> lqw = new LambdaUpdateWrapper<>();
        lqw.set(SysUser::getStatus,bo.getStatus())
            .eq(SysUser::getId,bo.getId());
        int update = baseMapper.update(null, lqw);
        return update>0;
    }

    /**
     * 删除用户和对应的权限的关联信息
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public Boolean delete(Integer userId) {
        LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysUser::getDelFlag, YesOrNo.YES.getCode());
        lqw.in(SysUser::getId, userId);
        List<SysUser> sysUsers = baseMapper.selectList(lqw);
        AssertUtil.isNotEmpty(sysUsers, "用户不存在");
        int update = baseMapper.update(null, new LambdaUpdateWrapper<SysUser>()
                .set(SysUser::getDelFlag, YesOrNo.NO.getCode())
                .set(SysUser::getUpdateTime, DateUtils.getLocalDateTime())
                .in(SysUser::getId, sysUsers.stream().map(SysUser::getId).collect(Collectors.toSet())));
        LambdaQueryWrapper<UserRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserRole::getUserId,userId);
        boolean remove = userRoleService.remove(lambdaQueryWrapper);
        return update > 0 && remove;
    }

    /**
     * 重置密码
     * @param bo
     * @return
     */
    @Override
    public Boolean resetPassword(UpdateUserPsBo bo) {
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper();
        lqw.eq(SysUser::getDelFlag, YesOrNo.NO.getCode());
        lqw.in(SysUser::getId, bo.getId());
        List<SysUser> sysUsers = baseMapper.selectList(lqw);
        AssertUtil.isNotEmpty(sysUsers, "用户不存在");
        String password = MD5Utils.stringToMD5("123456");
        int update = baseMapper.update(null,new LambdaUpdateWrapper<SysUser>()
            .set(SysUser::getPassword,password)
            .eq(SysUser::getId,bo.getId()));
        return update > 0;
    }

    /**
     * 更新密码
     * @param bo
     * @return
     */
    @Override
    public Boolean changePassword(UpdateUserChangePsBo bo) {
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper();
        lqw.eq(SysUser::getDelFlag, YesOrNo.NO.getCode());
        lqw.eq(SysUser::getId, UserContext.get().getId());
        SysUser sysUser = baseMapper.selectOne(lqw);
        AssertUtil.isNotNull(sysUser, "用户不存在");

        bo.setOldPassword(MD5Utils.stringToMD5(bo.getOldPassword()));
        bo.setNewPassword(MD5Utils.stringToMD5(bo.getNewPassword()));
        AssertUtil.isTrue(sysUser.getPassword().equals(bo.getOldPassword()),"旧密码不正确");
        int update = baseMapper.update(null,new LambdaUpdateWrapper<SysUser>()
                    .set(SysUser::getPassword,bo.getNewPassword())
                    .eq(SysUser::getId,UserContext.get().getId()));
        return update > 0;
    }

    /**
     * 分页查询用户信息
     * @param bo
     * @return
     */
    @Override
    public List<UserVo> qryByPaged(QueryUserListReqBo bo) {
        MyPageHelper.startPage(bo);
        LambdaQueryWrapper<SysUser> lqw=new LambdaQueryWrapper<>();
        if(bo.getUsername()!=null && bo.getUsername().length()>0){
            lqw.like(SysUser::getUsername,bo.getUsername());
        }
        lqw.eq(SysUser::getDelFlag,YesOrNo.YES.getCode());
        List<SysUser> mos = list(lqw);
        return entity2Vo(mos);
    }

    /**
     * 格式转换和映射对象的权限信息
     * @param collection
     * @return
     */
    private List<UserVo> entity2Vo(Collection<SysUser> collection) {
        List<UserVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, UserVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<SysUser> page = (Page<SysUser>) collection;
            Page<UserVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        //映射角色名称
        voList.forEach(vo->{
            List<SysRole> currentRoleList = sysRoleService.list(new LambdaQueryWrapper<SysRole>().inSql(SysRole::getId, "select roleId from user_role where userId="+vo.getId()));
            vo.setRoleName(String.join(" ",currentRoleList.stream().map(SysRole::getRoleName).collect(Collectors.toList())));
            vo.setRoleIdList(currentRoleList.stream().map(SysRole::getId).collect(Collectors.toList()));
        });

        return voList;
    }
}
